﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using gxc2csharp.Translator.GxcToCTransform;
using Antlr.Runtime;
using Antlr.Runtime.Tree;
using System.IO;
using GxcToCsharpParser.GrcParser;

namespace Gxc2CsharpConsonle
{
   class Gxc2CsharpBuilder
   {
      public GrcParser GrcParser{get;set;}
      public GxcParser Gxcparser { get; set; }
      private string gppTempFile;
      public bool isGxcFileParsable;
      public void Build(string gxcFilePath,string grcFilePath)
      {
         /*ParseGrcFile(@"..\..\..\gxc2csharpTranslator.Tests\data\rangrid.grc");
         p.GrcExecute(@"..\..\..\gxc2csharpTranslator.Tests\data\rangrid.grc");
         p.GppExecute(@"..\..\..\gxc2csharpTranslator.Tests\data\rangrid.gxc");
         p.ParseCFile("temp_gpp.c");*/
       
         ParseGrcFile(grcFilePath);
         GrcExecute(grcFilePath);
         GppExecute(gxcFilePath);
         Console.Error.WriteLine("Antlr Parsing " + gppTempFile);
         ParseCFile(@".\temp\"+gppTempFile);
         
         
         
      }
      private void GrcExecute(string grcFilePath)
      {
         if (File.Exists(grcFilePath))
         {
            System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("grc.exe", grcFilePath);
            info.RedirectStandardError = true;
            info.UseShellExecute = false;
            info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            try
            {
               System.Diagnostics.Process p = System.Diagnostics.Process.Start(info);
               p.WaitForExit();
               if (p.ExitCode != 0)
               {
                  DumpErrors(p.StandardError);
                  throw new Exception("Grc File:" + grcFilePath + " is not well formed");
               }
            }
            catch (Exception e)
            {
               Console.WriteLine("Unable to run grc.exe.Please check if it's on the system path");
            }
         }
         else
         {
            Console.WriteLine("Unable to find grc file. File may not be present or Include path is wrong.");
         }

      }

      private void DumpErrors(StreamReader streamReader)
      {
         while (streamReader.EndOfStream != true)
         {
            Console.WriteLine(streamReader.ReadLine());
         }
      }
      private void GppExecute(string gxcFilePath)
      {
         gppTempFile = Path.GetFileName(gxcFilePath);
         System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("gpp.exe", "-P " + gxcFilePath + @" .\temp\" + gppTempFile);
         info.RedirectStandardError = true;
         info.UseShellExecute = false;
         info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
         try
         {
            System.Diagnostics.Process p = System.Diagnostics.Process.Start(info);
            p.WaitForExit();
            if (p.ExitCode != 0)
            {
               DumpErrors(p.StandardError);
               throw new Exception("Gxc File :" + gxcFilePath + " is not well formed");
            }
         }
         catch (Exception e)
         {
            Console.WriteLine("Unable to run grc.exe.Please check if it's on the system path");
         }

      }
      private void ParseGrcFile(string grcFilePath)
      {
         Console.WriteLine("Parsing GRC File ");
         GrcParser = new GrcParser();
         GrcParser.ParseFile(grcFilePath);
         Console.WriteLine("Done Parsing GRC File ");

      }
      private CommonTree ParseCFile(string cFile)
      {
         Console.WriteLine("Parsing GXC File ");
         StreamReader reader = new StreamReader(cFile);
         ANTLRReaderStream antlrReader = new ANTLRReaderStream(reader);
         GxcLexer lex = new GxcLexer(antlrReader);
       
         CommonTokenStream tokens = new CommonTokenStream(lex);
     
         Gxcparser = new GxcParser(tokens);

         CommonTree gxcAbastractSyntaxTree =null;
         isGxcFileParsable = true;
         try
         {
            GxcParser.translation_unit_return program = Gxcparser.translation_unit();
            gxcAbastractSyntaxTree = (CommonTree)program.Tree;

            Gxcparser.LinesOfCode = lex.LinesOfCode;
            var metrics = Gxcparser.GetMetrics();
            Console.WriteLine("Done Parsing GXC File ");
            Console.WriteLine(metrics.ToString());

         }
         catch (RecognitionException e)
         {
            Console.Error.WriteLine(e.StackTrace);
            isGxcFileParsable = false;
         }
         return gxcAbastractSyntaxTree;
      }



      public CommonTree ParseGxcFileOnly(string gxcFilePath)
      {
         return ParseCFile(gxcFilePath);
      }

      internal void Stats()
      {
         Console.WriteLine("Variables {0}", Gxcparser.GxVariables.Count);
         Console.WriteLine("Pinvokes {0}", Gxcparser.PInvokeFunctions.Count);
      }
   }
}
